package com.anrong.wulansdk.sdk;

import android.Manifest;
import android.annotation.TargetApi;
import android.app.Application;
import android.app.Service;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
import android.text.TextUtils;
import android.util.Log;

import com.anrong.wulansdk.sdk.constant.Constant;
import com.anrong.wulansdk.sdk.constant.EventId;
import com.anrong.wulansdk.sdk.db.LiteOrmDBUtil;
import com.anrong.wulansdk.sdk.entity.EventLog;
import com.anrong.wulansdk.sdk.entity.UploadInfo;
import com.anrong.wulansdk.sdk.service.UploadService;
import com.anrong.wulansdk.sdk.utils.MyLocation;
import com.anrong.wulansdk.sdk.utils.MyLogcat;
import com.anrong.wulansdk.sdk.utils.PreferenceUtil;
import com.anrong.wulansdk.sdk.utils.Utils;

import java.text.SimpleDateFormat;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;


/**
 * 主类
 * @author cxy
 *
 */
public class WLData {
	
	private static SimpleDateFormat sdf = new SimpleDateFormat("MM-dd HH:mm:ss");
	
	private volatile static WLData mIntance;
	private static Application app;
	private static Context context;
	private static Object INSTANCE_LOCK = new Object();
	
	private static WLConfig config;
	private static Intent service;
	
	private final static int TIMER = 1;
	private static Handler h = new Handler(){
		public void handleMessage(android.os.Message msg) {
			switch (msg.what) {
			case TIMER:
				PreferenceUtil.putString(context, APP_END_TIME, System.currentTimeMillis()+"");
//				Log.i("wulan", "task~~~~~~~~~~~~~~~~~~~~~~~~");
				break;

			default:
				break;
			}
		}
	};
	
	private static final String SPLIT = "%_";

	private WLData() {};
	
	//线程池
	private static ExecutorService executorService;

	private static ServiceConnection conn;
	/** 线程池大小 */
	private static final int THREAD_SIZE = 10;
	
	private static boolean isInit = false;
	
	/**
	 * 单例
	 */
//	public static WLData getInstance() {
//		if (mIntance == null) {
//			synchronized (INSTANCE_LOCK) {
//				if (mIntance == null) {
//				}
//			}	
//		}
//		return mIntance;
//	}
	
	/** 初始化 */
	public static void init(WLConfig wlConfig){
		config = wlConfig;
		app = config.getApp();
		context = app.getApplicationContext();
		
		//TODO 先判断权限
		if (!checkPermission()) {
			return;
		}
		
		if (TextUtils.isEmpty(AppKey.appKey)) {
			MyLogcat.e("===========AppKey is Empty!!!!!!!!!!============");
			return;
		}
		
		/**初始化okhttp*/
//		initOkHttp();
		/**初始化数据库*/
		LiteOrmDBUtil.createCascadeDB(context);
		/**初始化定位*/
		MyLocation.init(context);
		
		/**自定义全局异常捕获*/
	//	CrashHandler.getInstance().init(context);
		
		createThreadPool();
		
		startUploadService();
		
		isInit = true;
	}

	/**
	 * 检查权限
	 * @return
	 */
	@TargetApi(23)
	private static boolean checkPermission() {
		if (Build.VERSION.SDK_INT >= 23) {
			int write = context.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE);
			if (write != PackageManager.PERMISSION_GRANTED) {
				Log.d("main", "WLSDK 未获取内存读写权限, 初始化失败");
				return false;
			}
			return true;
		}
		return true;
	}

	
	/**
	 * 创建线程池
	 */
	private static void createThreadPool() {
		//创建一个线程数为10的线程池
		executorService = Executors.newFixedThreadPool(THREAD_SIZE);
	}

	/**
	 * 开启上传服务
	 */
	private static void startUploadService() {
		
		if (!Utils.isServiceWork(context, "com.anrong.wulansdk.sdk.service.UploadService")) {
			MyLogcat.log("wulan: 服务未运行, 准备开启");
			service = new Intent(context, UploadService.class);
//			context.startService(service);
			conn = new ServiceConnection() {
				
				@Override
				public void onServiceDisconnected(ComponentName name) {
					
				}
				
				@Override
				public void onServiceConnected(ComponentName name, IBinder service) {
//					UploadService.MyBinder myBinder = (UploadService.MyBinder)service;
//					UploadService uploadService = myBinder.getService();
//					uploadService.resetTimer();
					MyLogcat.log("onServiceConnected");
				}
			};
			context.bindService(service, conn, Service.BIND_AUTO_CREATE);
		}else {
			MyLogcat.log("wulan: 服务已经在运行");
		}
		
	}
	
//	/**
//	 * 初始化okhttp
//	 */
//	private static void initOkHttp() {
//
//		// HttpHeaders headers = new HttpHeaders();
//		// headers.put("commonHeaderKey1", "commonHeaderValue1"); // 所有的 header
//		// headers.put("commonHeaderKey2", "commonHeaderValue2");
//		// HttpParams params = new HttpParams();
//		// params.put("commonParamsKey1", "commonParamsValue1"); // 所有的 params 都支持中文
//		// params.put("commonParamsKey2", "这里支持中文参数");
//		OkHttpUtils.init(app);
//		// 以下都不是必须的，根据需要自行选择
//		OkHttpUtils.getInstance()//
////				.debug("OkHttpUtils") // 是否打开调试
//				.setConnectTimeout(OkHttpUtils.DEFAULT_MILLISECONDS) // 全局的连接超时时间
//				.setReadTimeOut(OkHttpUtils.DEFAULT_MILLISECONDS) // 全局的读取超时时间
//				.setWriteTimeOut(OkHttpUtils.DEFAULT_MILLISECONDS);// 全局的写入超时时间
//		// .addCommonHeaders(headers) // 设置全局公共头
//		// .addCommonParams(params);//添加公共参数
//	}
	
	/**
	 * 获取WLConfig
	 * @return
	 */
	public static WLConfig getConfig(){
		return config;
	}
	
	
	
	/**
	 * 检测传入信息
	 * @param accountId
	 * @param event
	 * @param eventDesc
	 * @return
	 */
//	private boolean checkInfo(final String accountId, final String event, final String eventDesc) {
//		if (TextUtils.isEmpty(accountId) || TextUtils.isEmpty(event) ||TextUtils.isEmpty(eventDesc)) {
//			MyLogcat.e("上报信息参数不能为空");
//			return false;
//		}
//		eventDesc.matches()
//		//    [A-Za-z0-9_]+/[A-Za-z0-9_]+/[A-Za-z0-9_]+/[A-Za-z0-9_]+
//		String re = "[A-Za-z0-9_]+/[A-Za-z0-9_]+/[A-Za-z0-9_]+/[A-Za-z0-9_]+";
//		if (!eventDesc.matches(re)) {
//			MyLogcat.e("上报信息参数格式不正确:"+eventDesc);
//			return false;
//		}
//		return true;
//	}
	

	
	
	/**
	 * 上报事件
	 * @param eventId
	 * @param eventDesc
	 */
	private static void onEvent(String eventId, String eventDesc){
		onEventMapping(eventId, eventDesc, null);
	}
	
	private static void onMappingWithoutEvent(Map<String, String> map){
		onEventMapping(null, null, map);
	}
	private static  void onJilinEvent(Map<String,String>map){
		if(map!=null&&map.size()!=0){
			onMyBase(getAccountKey(),map);
		}
	}

	private static void onEventMapping(String eventId, String eventDesc, Map<String, String> map){
		if (map != null && map.size() != 0) {
			StringBuffer mapping = new StringBuffer(), mappingDesc = new StringBuffer();
			
			for (Map.Entry<String, String> entry : map.entrySet()) {
			   mapping.append(entry.getKey()+SPLIT);
			   mappingDesc.append(entry.getValue()+SPLIT);
			}
			
			onBase(getAccountKey(), eventId, eventDesc, mapping.substring(0, mapping.length()-SPLIT.length()), mappingDesc.substring(0, mappingDesc.length()-SPLIT.length()));
		}else{
			onBase(getAccountKey(), eventId, eventDesc, null, null);
		}
	}
	
	
	/**
	 * 汇总方法  保存到数据库
	 * @param accountKey
	 * @param eventId
	 * @param eventDesc
	 * @param mapping
	 * @param mappingDesc
	 */
	private static void onBase(final String accountKey, final String eventId, final String eventDesc, final String mapping, final String mappingDesc){
		if (context == null || executorService == null) {
			MyLogcat.e("WuLanSDK not init");
			return;
		}
		if (TextUtils.isEmpty(accountKey)) {
			MyLogcat.e("accountKey is empty!");
//			return;
		}
		executorService.submit(new Runnable() {
			@Override
			public void run() {
				
				UploadInfo info = new UploadInfo();
				info.setLogType("Android");
				info.setAppKey(AppKey.appKey);
				info.setDeviceId(Utils.getImei(context));
				info.setAccountKey(accountKey);
				info.setAppVersion(Utils.getVersionName(context));
				info.setIp(Utils.getIP(context));
				info.setPlatform(Constant.ANDROID);
				info.setVendor(Utils.getModel());
				info.setOs(Utils.getOS());
				info.setCarrier(Utils.getOperators(context));
				info.setNetwork(Utils.getNetwork(context));
				info.setRecordTime(System.currentTimeMillis());
				info.setSendTime(System.currentTimeMillis());
				info.setEvent(eventId);
				info.setEventDesc(eventDesc);
				info.setMac(Utils.getMac(context));
				info.setMapping(mapping);
				info.setMappingDesc(mappingDesc);
//				if (initLocation()) {
					info.setLongitude(MyLocation.getLongitude());
					info.setLatitude(MyLocation.getLatitude());
					info.setAltitude(MyLocation.getAltitude());
					info.setCity(MyLocation.getCity());
					info.setProvince(MyLocation.getProvince());
					info.setCountry("中国");
//				}

					MyLogcat.log("eventId:"+eventId+", eventDesc:"+eventDesc+", mapping:"+mapping+", mappingDesc:"+mappingDesc);
				
				//保存到本地数据库，等到service中上传
				long insertLog = LiteOrmDBUtil.insert(info);
				info = null;
			}
		});

		//开启服务.
		startUploadService();
		
	}

	/**
	 * 吉林汇总方法  保存到数据库
	 * @param accountKey
	 * @param
	 * @param
	 */
	private static void onMyBase(final String accountKey, final Map<String,String>map){
		if (context == null || executorService == null) {
			MyLogcat.e("WuLanSDK not init");
			return;
		}
		if (TextUtils.isEmpty(accountKey)) {
			MyLogcat.e("accountKey is empty!");
			//			return;
		}
		executorService.submit(new Runnable() {
			@Override
			public void run() {
				EventLog info = new EventLog();
				info.setSid(map.get("sid"));
				info.setDevId(Utils.getImei(context));
				info.setUserId(map.get("userid"));//TF卡帐号
				info.setAppCode(map.get("appcode"));//应用唯一标识  包名
				info.setStaffCode(accountKey);//警员号
				info.setMac(Utils.getMac(context));
				info.setIp(Utils.getIP(context));
				info.setLongitude(MyLocation.getLongitude());
				info.setLatitude(MyLocation.getLatitude());
				info.setAltitude(MyLocation.getAltitude());
				info.setEventName(map.get("evenname"));
				info.setEventPath(map.get("evenpath"));
				info.setEventDesc(map.get("evendes"));
				info.setStartTime(System.currentTimeMillis());
				info.setEndTime(System.currentTimeMillis());
				info.setResult(map.get("result"));
				info.setResultErr(map.get("result_erro"));

				MyLogcat.log("imei:"+Utils.getImei(context)+", eventname:"+map.get("evenname")+", eventdes:"+map.get("evendes"));

				//保存到本地数据库，等到service中上传
				long insertLog = LiteOrmDBUtil.insert(info);
				info = null;
			}
		});

		//开启服务.
		startUploadService();

	}
	//************************************************app使用时间统计***********************************
	
	/**
	 * app开始时调用, 用于记录app使用时长
	 * @param
	 */
	public static void onAppStart(){
		if (isInit) {
			onEvent(EventId.START, "");
			setAppTimer();
			PreferenceUtil.putString(context, APP_START_TIME, System.currentTimeMillis()+"");
		}
	}
	
	/**
	 * app结束时调用, 用于记录app使用时长
	 * @param
	 */
	public static void onAppEnd(){
		if (isInit) {
			//如果调用了此方法,则把计时器取消,并清空保存的时间,用当前时间作为app结束的时间
			if (task != null) {
				task.cancel();
				task = null;
			}
			if (timer != null) {
				timer.cancel();
				timer = null;
			}
			String endTime = PreferenceUtil.getString(context, APP_END_TIME);
			PreferenceUtil.putString(context, APP_END_TIME, "");
			sendAppUseTime(endTime);

			context.unbindService(conn);
		}
	}

	/**
	 * 上报app使用时间
	 * @param
	 */
	private static void sendAppUseTime(String endTime) {
		if (isInit) {
		
			if (TextUtils.isEmpty(endTime)) {
				return;
			}
			String startTime = PreferenceUtil.getString(context, APP_START_TIME);
			if (TextUtils.isEmpty(startTime)) {
				MyLogcat.e("app starttime is null!");
				return;
			}
	//		String endTime = System.currentTimeMillis()+"";
	//		onEvent(EventId.APP_USETIME, sdf.format(Long.valueOf(startTime))+"#"+sdf.format(Long.valueOf(endTime)));
			onEvent(EventId.APP_USETIME, startTime+"#"+endTime);
		}
	}
	
	//*************************************************************************************************
	
	
	//************************************************页面时间统计***********************************
	
	/**记录所有访问页面的开始时间, key为页面名称, value为访问页面的开始时间*/
//	private static Map<String, String> pageStartTimeMap = new HashMap<String, String>();
	
	/**
	 * 页面开始
	 * @param pageName	页面名称
	 */
	public static void onPageStart(String pageName){
		if (isInit) {
	//		pageStartTimeMap.put(pageName, System.currentTimeMillis()+"");
			PreferenceUtil.putString(context, pageName, System.currentTimeMillis()+"");
		}
	}
	
	/**
	 * 页面结束
	 * @param pageName	页面名称
	 */
	public static void onPageStop(String pageName){
		if (isInit) {
			onPageStop(pageName, null);
		}
	}
	public static void onPageStop(String pageName, Map<String, String> map){
		if (isInit) {
			String startTime = PreferenceUtil.getString(context, pageName);
			PreferenceUtil.putString(context, pageName, "");
			if (TextUtils.isEmpty(startTime)) {
				MyLogcat.e(pageName+": no pageStart time");
				return;
			}
	//		String endTime = Utils.getCurrentUTCTime();
	//		onEventMapping(EventId.PAGE, pageName+"#"+sdf.format(Long.valueOf(startTime))+"#"+sdf.format(System.currentTimeMillis()), map);
			onEventMapping(EventId.PAGE, pageName+"#"+startTime+"#"+System.currentTimeMillis(), map);
		}
	}
	
	//*************************************************************************************************
	
	//************************************************请求响应时长统计***********************************
	
	/**记录请求响应时长, 成对调用*/
//	private static Map<String, String> requestStartTimeMap = new HashMap<String, String>();
	
	/**
	 * 请求开始时间记录
	 * @param requestName	请求名称
	 */
	public static void onRequest(String requestName){
		if (isInit) {
		PreferenceUtil.putString(context, requestName, System.currentTimeMillis()+"");
		}
	}
	
	/**
	 * 请求结束时间记录
	 * @param requestName	请求名称
	 */
	public static void onResponse(String requestName){
		if (isInit) {
		onResponse(requestName, null);
		}
	}
	
	public static void onResponse(String requestName, Map<String, String> map){
		if (isInit) {
		String startTime = PreferenceUtil.getString(context, requestName);
		PreferenceUtil.putString(context, requestName, "");
		if (TextUtils.isEmpty(startTime)) {
			MyLogcat.e(requestName+": on request time");
			return;
		}
//		String endTime = Utils.getCurrentUTCTime();
		onEventMapping(EventId.PAGE, requestName+"#"+startTime+"#"+System.currentTimeMillis(), map);
		}
	}
	
	//*************************************************************************************************
	
	
	/**
	 * 系统异常上报
	 * @param name	错误名称标识
	 * @param exceptionInfo	格式: 包名#异常信息  list	扩展参数
	 * @param
	 */
	public static void onSysException(String name, String exceptionInfo, Map<String, String> map){
		if (isInit) {
		onEventMapping(EventId.EXCEPTION_SYS, name+"#"+exceptionInfo, map);
		}
	}
	public static void onSysException(String name, String exceptionInfo){
		if (isInit) {
		onSysException(name, exceptionInfo, null);
		}
	}
	/**
	 * 业务异常上报
	 * @param name	错误名称标识
	 * @param location	错误位置标识
	 * @param
	 */
	public static void onBusException(String name, String location, Map<String, String> map){
		if (isInit) {
			onEventMapping(EventId.EXCEPTION_BUS, name+"#"+location, map);
		}
	}
	public static void onBusException(String name, String location){
		if (isInit) {
			onBusException(name, location, null);
		}
	}
	
	/**
	 * 模块调用上报
	 * @param
	 * @param modelName
	 */
	public static void onModel(String modelName){
		if (isInit) {
			onModel(modelName, null);
		}
	}
	public static void onModel(String modelName, Map<String, String> map){
		if (isInit) {
			onEventMapping(EventId.MODEL, modelName, map);
		}
	}
	
	//*************************************************************************************************
	
	/**
	 * 流程事件
	 * @param processEventId	事件id
	 * @param currentProcess	流程的进度标识
	 */
	public static void onProcessEvent(String processEventId, String currentProcess){
		if (isInit) {
			onProcessEvent(processEventId, currentProcess, null);
		}
	}
	public static void onProcessEvent(String processEventId, String currentProcess, Map<String, String> map){
		if (isInit) {
			onEventMapping(EventId.SELF, processEventId+"#"+currentProcess, map);
		}
	}
	
	//*************************************************************************************************
	
	/**
	 * mapping
	 * @param
	 */
	public static void onMapping(Map<String, String> map){
		if (isInit) {
			onMappingWithoutEvent(map);
		}
	}
	
	//*************************************************************************************************
	
	/**
	 * 设置当前用户  acountId	用户唯一标识
	 * @param
	 */
	public static void setAccountKey(String accountKey){
		if (isInit) {
			PreferenceUtil.putString(context, PreferenceUtil.CURRENT_USER, accountKey);
		}
	}
	/**
	 * 获取设置的当前人员id
	 * @return
	 */
	public static String getAccountKey(){
		if (isInit) {
			return PreferenceUtil.getString(context, PreferenceUtil.CURRENT_USER);
		}else{
			return "";
		}
	}
	
	
	
	//**********************************************app使用时长计时器***********************************************
	
	/**记录时间的间隔*/
	private static final long TIMER_PERIOD = 1*1000;
	private static final String APP_START_TIME = "appStartTime";
	private static final String APP_END_TIME = "appEndTime";
	private static Timer timer;
	private static TimerTask task;
	
	/**
	 * 记录时间
	 * 从app开始运行时,每隔固定的时间记录一次时间,最后一次时间则为app退出时的时间(并不是每次app退出都一定会调用onAppEnd())
	 */
	private static void setAppTimer(){
		//如果上一次app关闭时间不为空,则表示上次结束时未调用onAppEnd方法,即没有记录app使用时长. 需要先记录上次使用时长
		if (!TextUtils.isEmpty(PreferenceUtil.getString(context, APP_END_TIME))) {
//			sendAppUseTime();
			onAppEnd();
		}
		if (task != null) {
			task.cancel();
		}
	
		task = new TimerTask() {
			@Override
			public void run() {
				h.obtainMessage(TIMER).sendToTarget();
			}
		};
		
		if (timer == null) {
			timer = new Timer();
		}
		
		timer.schedule(task, 0, TIMER_PERIOD);
	}
	
}
